module sidearm.symtab;

import std.stdio;
import std.stdint;
import std.string;

enum SymbolType
{
	Unknown,
	NonTerminal,
	Terminal,
	Whitespace,
	EOF,
	EOL,
	CommentStart,	// /*
	CommentEnd,		// */
	CommentLine,	// // or ; or --
	Special,	// , : ( ) \ etc
	Error
}

enum SymbolValue
{
	Byte, UByte, Word, UWord,
	Short, Long, ULong, String,
	Pointer, Array, Double
}

string fullSymbolTypeToString(SymbolType t)
{
	return typeof(t).stringof ~ "." ~ toString(t);
}

struct Symbol
{
	string name = null;
	SymbolType type = SymbolType.Unknown;
	uint id = -1;
	private static uint __base_id = 0;
	union v {
		byte	b;
		ubyte	ub;
		uint16_t	uw;
		int16_t	w;
		uint24_t	us;
		int32_t	l;
		uint32_t	ul;
		string	s;
		double d;
	}
	uint	lineno = 1;
	SymbolValue val;

	this(string n, SymbolType t, uint i=0)
	{
		name = n;
		type = t;
		if (i) id = i;
		else i = getID();
	}

	static uint getID() { return __base_id++; }

	string toString()
	{
		return
			"%s( %s,%s,%s )".format(typeof(this).stringof,
				  name.escapeDDQS(),
				  fullSymbolTypeToString(type),
				  id
			  );
	}
	T val;
}

// most common hash symtab algo used by ELF files
ulong defaultSymtabHash(const ubyte * name)
{
	ulong h = 0, g;

	while(*name)
	{
		h = (h<<4)+*name++;
		if (g = h & 0xf0000000)
			h ^= g >> 24;
		h &= ~g;
	}
	return h;
}
/+++ SymbolTable
 +
 +/
class SymbolTable
{
public:

private:
	Symbol[string] _symbols;
}